Skip to content

feat(header, footer, tab-bar): add scrollEffect prop#31263

Open
OS-susmitabhowmik wants to merge 72 commits into
nextfrom
ROU-12870-scroll-effect
Open

feat(header, footer, tab-bar): add scrollEffect prop#31263
OS-susmitabhowmik wants to merge 72 commits into
nextfrom
ROU-12870-scroll-effect

Conversation

@OS-susmitabhowmik

@OS-susmitabhowmik OS-susmitabhowmik commented Jul 10, 2026

Copy link
Copy Markdown

Issue number: resolves internal


What is the current behavior?

  • ion-header and ion-footer have a collapse prop for scroll-driven effects (condense, fade), but it only works on the iOS theme.
  • ion-tab-bar has an unreleased hideOnScroll boolean prop that only works on the Ionic theme with expand="compact".

What is the new behavior?

  • Adds a new scrollEffect string enum prop to ion-header, ion-footer, and ion-tab-bar.
  • scrollEffect="hide" slides the bar out of view when scrolling down and back in when scrolling up.
  • scrollEffect="condense" and scrollEffect="fade" on ion-header/ion-footer replace the existing collapse values and work across all themes.
  • Deprecates the collapse prop on ion-header and ion-footer with a console warning directing developers to use scrollEffect.
  • Removes the unreleased hideOnScroll prop from ion-tab-bar.
  • When ion-tab-bar is nested inside ion-footer, the footer owns the hide animation to prevent double-animation

Does this introduce a breaking change?

  • Yes
  • No

Other information

Relevant Test Pages:

Header

Footer

Tab Bar

@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ionic-framework Ready Ready Preview, Comment Jul 22, 2026 10:44pm

Request Review

@github-actions github-actions Bot added package: core @ionic/core package package: angular @ionic/angular package package: vue @ionic/vue package package: react @ionic/react package labels Jul 10, 2026
@OS-susmitabhowmik
OS-susmitabhowmik marked this pull request as ready for review July 13, 2026 17:01
@OS-susmitabhowmik
OS-susmitabhowmik requested a review from a team as a code owner July 13, 2026 17:01
@OS-susmitabhowmik
OS-susmitabhowmik requested a review from ShaneK July 13, 2026 17:01

@ShaneK ShaneK left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, great work on this! I highlighted a few issues I found, some of them aren't as important as others, but still

Comment thread core/src/components/header/header.tsx
Comment thread core/src/utils/content/index.ts Outdated
Comment thread core/src/components/footer/footer.tsx
Comment thread core/src/components/header/header.tsx
Comment thread core/src/components/tab-bar/tab-bar.tsx
Comment thread core/src/components/footer/footer.tsx
Comment thread core/src/components/tab-bar/tab-bar.tsx Outdated
Comment thread core/src/utils/scroll-hide-controller.ts
@OS-susmitabhowmik
OS-susmitabhowmik requested a review from ShaneK July 21, 2026 17:33

@ShaneK ShaneK left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, I think we're finally getting close to getting this one wrapped up! Just a few more issues I noticed, but we're so close!

Comment thread core/src/utils/scroll-hide-controller.ts Outdated
Comment thread core/src/components/header/header.tsx Outdated
Comment thread core/src/utils/scroll-hide-controller.ts Outdated
Comment thread core/src/components/header/header.tsx Outdated
@OS-susmitabhowmik

Copy link
Copy Markdown
Author

Hey, I think we're finally getting close to getting this one wrapped up! Just a few more issues I noticed, but we're so close!

@ShaneK Thanks for all the help on this! I addressed your latest round of comments and also noticed that some tests were using the deprecated collapse property so I updated these to use scrollEffect. Could you please take another look?

@ShaneK ShaneK left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for those changes, we're looking amazing! Just a few remaining things I noticed and I think we're done after this!

Comment thread core/src/components/tab-bar/tab-bar.tsx Outdated
hiddenClass: 'tab-bar-scroll-hidden',
contentPartnerClass: 'content-tab-bar-hide-scroll-partner',
contentHiddenClass: 'content-tab-bar-hide-scroll-hidden',
shouldKeepAriaHidden: () => this.keyboardVisible,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
shouldKeepAriaHidden: () => this.keyboardVisible,
shouldKeepAriaHidden: () => this.keyboardVisible && this.el.getAttribute('slot') !== 'top',

I pulled the branch and hit this one: a slot="top" tab-bar can get left with aria-hidden="true" while it's fully visible. The keep-guard here is this.keyboardVisible, but the keyboard writer above only hides bottom bars (keyboardOpen && slot !== 'top'). So with the keyboard open on a top tab bar, scrolling down hides it (aria-hidden set, correct), then scrolling back up runs setHidden(false), which clears inert and the hidden class but keeps aria-hidden because keyboardVisible is still true. I reproduced it live: after scrolling back up the bar is inert=false, not scroll-hidden, but still aria-hidden="true" until the keyboard closes. Matching the guard to the keyboard writer fixes it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed 4127289

// --------------------------------------------------

:host(.tab-bar-hide-on-scroll) {
:host(.tab-bar-scroll-effect-hide) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think prefers-reduced-motion gets defeated for the ionic theme here. Since this file does @use "./tab-bar.common", common's reduced-motion transition: none block is emitted first, then these ionic rules re-declare transition at equal specificity further down, so they win under reduced motion. I checked with reduced-motion emulated: on md the shown and hidden durations are both 0s, but on ionic the show transition stays 0.2s and the compact hide stays 0.35s (only the full-expand hide gets suppressed), so a reduced-motion user still gets the slide. I think adding a @media (prefers-reduced-motion: reduce) override at the end of this file, or extending the common reduced-motion selector list to cover these ionic selectors, would close it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch! I added the prefers-reduced-motion block to the end of the ionic tab bar stylesheet in 62dd0f5

Comment thread core/src/components/header/header.tsx Outdated
return false;
}

this.scrollEl = await getScrollElement(contentEl);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker, more of a consistency thought now that the hide path has the nice promise-identity guard. The condense setup here (and setupFadeHeader, plus footer's setupFadeFooter) still attaches its IntersectionObserver and scroll listener after await getScrollElement with no equivalent guard, and for condense activeEffect is only set after the await. So if a re-render lands in that await window, a second setup spawns and the first observer plus listener leak, since the later assignment overwrites the reference and teardown only cleans one. This is pre-existing structure and this PR actually narrows the window, so I don't think it needs to block anything. Worth extending the same guard to condense/fade at some point, or a follow-up card? Up to you.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a guard to the condense and fade setup methods in this commit eba6da6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

package: angular @ionic/angular package package: core @ionic/core package package: react @ionic/react package package: vue @ionic/vue package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants